#define _XOPEN_SOURCE 

#include "tools.h"

void authentication(int peerfd){
	//身份验证
    char recvbuf[1000];
    char username[100];
    struct spwd *sp;
    char passwd[100];
    char salt[512]={0};
    int ret,retVal;
    int length=0;
    while(1){
        char temp[1000]="\n>> please input username:";
        ret = send(peerfd, temp, strlen(temp), 0);
        ERROR_CHECK(ret, -1, "send");
        
        ret = recv(peerfd,&length,4,0);
        ERROR_CHECK(ret, -1, "recv");
        memset(recvbuf,'\0',strlen(recvbuf));
        ret = recv(peerfd, recvbuf, length, 0);
        ERROR_CHECK(ret, -1, "recv");
        //printf("recvbuf:%s\n",recvbuf);

        if(ret>0){
            memset(username,'\0',sizeof(username));
            memcpy(username,recvbuf,getLength(recvbuf));
            printf("username: %s\n",username);
            //username[getLength(username)-1]='\0';
            if((sp=getspnam(username)) == NULL){
                printf("没有获取到用户名和密码\n");
                strcpy(temp,">> username error!\n");
                retVal = send(peerfd, temp, strlen(temp), 0);
                continue;
            }else{
                memset(temp,'\0',sizeof(temp));
                strcpy(temp,">> please input password:");//----匹配这个
                retVal = send(peerfd, temp, strlen(temp), 0);
                recv(peerfd,&length,4,0);
                memset(recvbuf,'\0',strlen(recvbuf));
                retVal = recv(peerfd, recvbuf, length, 0);
                if(retVal>0){
                    memset(passwd,'\0',sizeof(passwd));
                    memcpy(passwd,recvbuf,getLength(recvbuf));
                    puts("passwd: ******");
                    //passwd[getLength(passwd)-1]='\0';

                    get_salt(salt,sp->sp_pwdp);
   
                    //进行密码验证
                    if(strcmp(sp->sp_pwdp,crypt(passwd,salt)) == 0){
                        printf("密码验证通过!\n");  
                        memset(temp,'\0',sizeof(temp));
                        strcpy(temp,">> login success!\n");  //---匹配这个
                        retVal = send(peerfd, temp, strlen(temp), 0);
                        break;
                    }else{
                        strcpy(temp,">> password error!\n");
                        retVal = send(peerfd, temp, strlen(temp), 0);
                        printf("密码验证失败!\n");
                        continue;
                    }
                }
            }
        }
        
        if (0 == ret) {
            printf("connect fd %d has closed in tools.c\n", peerfd);
            close(peerfd);
            break;
        }

        if (-1 == ret) {
            puts("authentication error");
        }
    }
    return;
}

void error_quit(char *msg) {
	perror(msg);
	exit(-2);
}

//获取盐值
void get_salt(char *salt,char *passwd) {
	int i,j;
	//取出 salt,i 记录密码字符下标,j 记录$出现次数
	for(i=0,j=0;passwd[i] && j != 3;++i) {
	    if(passwd[i] == '$') ++j;
	}
	strncpy(salt,passwd,i-1);
}

//拼接字符串
void concat(int len, char* str, char ch) {
	str += len;
	*str = ch;
	*(++str) = '\0';
	return;
}

//获取字符串的长度
int getLength(char* str) {
	int len = 0, k;
	for (k = 0; k < 2000; k++) {
		if (str[k] != '\0') {
			len++;
		}
		else {
			break;
		}
	}
	return len;
}
 
void load_config_file(char* file,char* ip,uint16_t* pport,int* pprocessNum){
    //加载配置文件
    int filefd=open(file,O_RDONLY);
    char confBuff[1000];
    memset(confBuff,'\0',sizeof(confBuff));
    read(filefd,confBuff,sizeof(confBuff));
    close(filefd);
    //printf("%d\n%s\n",getLength(confBuff),confBuff);

    //获取配置项，和对应的值
    char item[16];
    char value[16];
    memset(item,'\0',sizeof(item));
    memset(value,'\0',sizeof(value));
    int length=getLength(confBuff);
    int cnt=0;
    while(cnt<length){
        char ch = confBuff[cnt];

        if (ch=='\n' || ch == ' ' || ch == '\0' || ch=='\t' || ch=='\r') {
                    ;
        }else if(ch==':'){
            cnt++;
            ch=confBuff[cnt];
            while (ch!='\n') {
                if(ch!=' ' && ch!='\0'){
				    concat(getLength(value),value, ch);      //将ch连接在value后面
                }
				cnt++;                //指针向后移一位
				ch =confBuff[cnt];    //ch变为下一个ch
			}
            cnt--;
            
            if(strcmp(item,"ip")==0){
                memcpy(ip,value,getLength(value));
            }else if(strcmp(item,"port")==0){
                *pport=atoi(value);
            }else if(strcmp(item,"num")==0){
                *pprocessNum=atoi(value);
            }else{
                printf("configuration error\n");
            }
            
            memset(item,'\0',sizeof(item));
            memset(value,'\0',sizeof(value));
        }else{
            while (ch!=':') {
				concat(getLength(item),item, ch);      //将ch连接在item后面
				cnt++;                //指针向后移一位
				ch =confBuff[cnt];    //ch变为下一个ch
			}
            cnt--;
        }

        cnt++;
    }
    
    return;
}
